#include <xege.h>
#include <string>
#include <functional>

#include "button.h"

unsigned int GetUID () {
	static unsigned int n = 0;
	return ++n;
}

// 复制图像
void BUTTON::CopyImage (ege::PIMAGE Dst, ege::PIMAGE Src) {
	ege::getimage (Dst, Src, 0, 0, ege::getwidth (Dst), ege::getheight (Dst));
}

// 最大值
int BUTTON::Max (int a, int b) {
	return a > b ? a : b;
}
// 最小值
int BUTTON::Min (int a, int b) {
	return a > b ? b : a;
}
// 设置默认事件处理函数
void BUTTON::setDefault (void) {
	this->R2H = defaultFunc;
	this->H2R = defaultFunc;
	this->P2H = defaultFunc;
	this->H2P = defaultFunc;
	enableFlag = true;
	this->_UID = GetUID ();
	lastFlag = RELEASED;
}
// 检测鼠标事件
BUTTON::BUTTONFLAG BUTTON::CheckMouseEvent (mouse_msg _mouse) {
	// 当当前按钮启用时
	if (this->enableFlag) {
		// 根据 click 里面的内容检测是否该响应按钮事件
		if (ege::getpixel (_mouse.x - this->X, _mouse.y - this->Y, Click)) {
			// 当按下，且没弹起
			if (_mouse.is_left () && !_mouse.is_up ()) {
				return PRESSED;
			} else {
				return HOVER;
			}
		} else {
			return RELEASED;
		}
	} else {
		return RELEASED;
	}
}
// true for putimage & false for putimage_withalpha
void BUTTON::showBase (mouse_msg msg, bool _flag) {
		switch (CheckMouseEvent (msg)) {
			case HOVER: {
				if (lastFlag == BUTTON::RELEASED) {
					R2H (this->_UID);
				} else if (lastFlag == PRESSED) {
					P2H (this->_UID);
				}
				lastFlag = HOVER;
				if (_flag) {
					ege::putimage (this->X, this->Y, Hover);
				} else {
					ege::putimage_withalpha (nullptr, Hover, this->X, this->Y);
				}
			} break;
			case RELEASED: {
				if (lastFlag == BUTTON::HOVER) {
					H2R (this->_UID);
				}
				lastFlag = RELEASED;
				if (_flag) {
					ege::putimage (this->X, this->Y, Released);
				} else {
					ege::putimage_withalpha (nullptr, Released, this->X, this->Y);
				}
			} break;
			case PRESSED: {
				if (lastFlag == BUTTON::HOVER) {
					H2P (this->_UID);
				}
				lastFlag = PRESSED;
				if (_flag) {
					ege::putimage (this->X, this->Y, Pressed);
				} else {
					ege::putimage_withalpha (nullptr, Pressed, this->X, this->Y);
				}
			} break;
			default: /*error*/ break;
		}
	}

// 返回一个自增的值，用于找寻按钮
unsigned int BUTTON::UID () {
	return _UID;
}
BUTTON::BUTTON (void) {
	setDefault ();
}

BUTTON::BUTTON (int X, int Y, int Width, int Height) {
	// 初始化
	// 得多写几个初始化函数，用以初始化按钮，比如用 ege::PIMAGE 初始化
	// 之类的，
	Hover = ege::newimage (Width, Height);
	Released = ege::newimage (Width, Height);
	Pressed = ege::newimage (Width, Height);
	Click = ege::newimage (Width, Height);

	// 绘制按钮
	ege::setfillcolor (GREEN, Hover);
	ege::setfillcolor (WHITE, Released);
	ege::setfillcolor (RED, Pressed);
	ege::setfillcolor (WHITE, Click);

	ege::bar (0, 0, Width, Height, Hover);
	ege::bar (0, 0, Width, Height, Released);
	ege::bar (0, 0, Width, Height, Pressed);
	ege::bar (0, 0, Width, Height, Click);
	// ege::fillellipse (50, 50, 50, 50, Click);
	// Click 是点击范围，只要不是纯黑色都是有效区域，
	// 这一圈只不过是用内置函数了，实际上可以用任何图片

	this->X = X;  this->Width = Width;
	this->Y = Y;  this->Height = Height;
	setDefault ();
}

BUTTON::BUTTON (int X, int Y, ege::PIMAGE Hover, ege::PIMAGE Released, ege::PIMAGE Pressed, ege::PIMAGE Click) {
	setImage (Hover, Released, Pressed, Click);
	setPos (X, Y);
	setDefault ();
}

// 启用/停用 按钮
void BUTTON::enable (bool _flag) {
	enableFlag = _flag;
}

// 设置按钮位置
void BUTTON::setPos (int x, int y) {
	this->X = x;
	this->Y = y;
}

// 设置按钮图像
void BUTTON::setImage (ege::PIMAGE Hover, ege::PIMAGE Released, ege::PIMAGE Pressed, ege::PIMAGE Click) {
	int HW = ege::getwidth (Hover),    HH = ege::getheight (Hover),
		RW = ege::getwidth (Released), RH = ege::getheight (Released),
		PW = ege::getwidth (Pressed),  PH = ege::getheight (Pressed);
	delimage (this->Hover);
	delimage (this->Released);
	delimage (this->Pressed);
	this->Hover    = ege::newimage (HW, HH);
	this->Released = ege::newimage (RW, RH);
	this->Pressed  = ege::newimage (PW, PH);

	if (Click == nullptr) {
		int MW = Max (HW, Max (RW, PW));
		int MH = Max (HH, Max (RH, PH));
		delimage (this->Click);
		this->Click = ege::newimage (MW, MH);
		ege::setfillcolor (WHITE, this->Click);
		ege::bar (0, 0, MW, MH, this->Click);
	} else {
		delimage (this->Click);
		this->Click = ege::newimage (ege::getwidth (Click), ege::getheight (Click));
		CopyImage (this->Click, Click);
	}
	// 有效面积最大化
	CopyImage (this->Hover, Hover);
	CopyImage (this->Released, Released);
	CopyImage (this->Pressed, Pressed);
	// ege::bar (0, 0, Width, Height, Pressed);
}

void BUTTON::Show (mouse_msg msg) {
	showBase (msg, true);
}
// 当按钮有透明颜色的时候，请使用这个
void BUTTON::ShowPNG (mouse_msg msg) {
	showBase (msg, false);
}
// 当按下返回 true 
bool BUTTON::isPressed (mouse_msg msg) {
	return CheckMouseEvent (msg) == BUTTON::PRESSED;
}
// 当释放返回 true
bool BUTTON::isReleased (mouse_msg msg) {
	return CheckMouseEvent (msg) == BUTTON::RELEASED;
}
// 当悬浮返回 true
bool BUTTON::isHover (mouse_msg msg) {
	return CheckMouseEvent (msg) == BUTTON::HOVER;
}
// 设置悬浮后按下的处理函数，传入一个参数，当前按钮的 id
void BUTTON::setH2R (std::function <void(unsigned int id)> func) {
	this->H2R = func;
}
// 设置按下后释放的处理函数，传入一个参数，当前按钮的 id
void BUTTON::setR2H (std::function <void(unsigned int id)> func) {
	this->R2H = func;
}
// 设置鼠标离开按钮的处理函数，传入一个参数，当前按钮的 id
void BUTTON::setH2P (std::function <void(unsigned int id)> func) {
	this->H2P = func;
}
// 设置鼠标进入按钮的处理函数，传入一个参数，当前按钮的 id
void BUTTON::setP2H (std::function <void(unsigned int id)> func) {
	this->P2H = func;
}

BUTTON::~BUTTON () {
	ege::delimage (Released);
	ege::delimage (Hover);
	ege::delimage (Pressed);
	ege::delimage (Click);
}